package com.thyme.controller;

import com.thyme.domain.News;
import com.thyme.repository.NewsRepository;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author thyme
 * @ClassName NewsController
 * @Description TODO
 * @Date 2020/5/7 14:46
 */
@RestController
@RequestMapping("/news")
public class NewsController {

    @Autowired
    private NewsRepository newsRepository;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @RequestMapping("/save")
    public News save(@RequestParam(value = "title") String title,
                       @RequestParam(value = "content") String content){
        News news = newsRepository.save(News.builder().title(title).content(content).build());
        return news;
    }

    @RequestMapping("/search")
    public Iterable<News> search(){
        return newsRepository.findAll();
    }

    @RequestMapping("/highlight_search")
    public AggregatedPage<News> highlightSearch(@RequestParam(value = "key") String key) {
        // 定义高亮字段
        HighlightBuilder.Field titleField = new HighlightBuilder.Field("title").preTags("<span>").postTags("</span>");
        HighlightBuilder.Field contentField = new HighlightBuilder.Field("content").preTags("<span>").postTags("</span>");
        // 构建查询内容
        QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(key);
        // 查询匹配的字段
        queryStringQueryBuilder.field("title").field("content");

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(queryStringQueryBuilder).withHighlightFields(titleField, contentField).build();
        AggregatedPage<News> news = elasticsearchTemplate.queryForPage(searchQuery, News.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
                List<News> list = new ArrayList<>();
                for (SearchHit hit : response.getHits()) {
                    if (response.getHits().getHits().length <= 0){
                        return null;
                    }
                    News news1 = new News();
                    HighlightField title = hit.getHighlightFields().get("title");
                    if (title != null) {
                        news1.setTitle(title.fragments()[0].toString());
                    }
                    HighlightField content = hit.getHighlightFields().get("content");
                    if (content != null) {
                        news1.setContent(content.fragments()[0].toString());
                    }
                    list.add(news1);
                }
                if (list.size() > 0) {
                    return new AggregatedPageImpl<>((List<T>) list);
                }
                return null;
            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                return null;
            }
        });
        return news;
    }

}
